package cn.com.wangluotongxin.merchants.service.impl;

import cn.com.wangluotongxin.admin.DAdminMerchantsInfoService;
import cn.com.wangluotongxin.admin.model.AdminMerchantsInfo;
import cn.com.wangluotongxin.chat.vo.SysUserVo;
import cn.com.wangluotongxin.common.constants.CommonConstant;
import cn.com.wangluotongxin.common.exceptions.BadResponseException;
import cn.com.wangluotongxin.common.pojo.TenantInfo;
import cn.com.wangluotongxin.common.pojo.TenantUser;
import cn.com.wangluotongxin.common.utils.TenantTokenUtil;
import cn.com.wangluotongxin.common.utils.TenantUtils;
import cn.com.wangluotongxin.common.utils.XXTeaUtil;
import cn.com.wangluotongxin.merchants.dto.UserDto;
import cn.com.wangluotongxin.merchants.form.UserEditForm;
import cn.com.wangluotongxin.merchants.form.UserForm;
import cn.com.wangluotongxin.merchants.model.MerchantsMenu;
import cn.com.wangluotongxin.merchants.model.MerchantsRole;
import cn.com.wangluotongxin.merchants.model.MerchantsUser;
import cn.com.wangluotongxin.merchants.mapper.MerchantsUserMapper;
import cn.com.wangluotongxin.merchants.model.MerchantsUserRole;
import cn.com.wangluotongxin.merchants.model.constants.MenuType;
import cn.com.wangluotongxin.merchants.model.constants.YesNo;
import cn.com.wangluotongxin.merchants.service.IMerchantsMenuService;
import cn.com.wangluotongxin.merchants.service.IMerchantsRoleService;
import cn.com.wangluotongxin.merchants.service.IMerchantsUserRoleService;
import cn.com.wangluotongxin.merchants.service.IMerchantsUserService;
import cn.com.wangluotongxin.merchants.vo.RoleVo;
import cn.com.wangluotongxin.merchants.vo.UserVo;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 商户管理-用户表 服务实现类
 * </p>
 *
 * @author AutoGenerator
 * @since 2024-04-26
 */
@Service
public class MerchantsUserServiceImpl extends ServiceImpl<MerchantsUserMapper, MerchantsUser> implements IMerchantsUserService {

    @Reference
    private DAdminMerchantsInfoService merchantsInfoService;
    @Autowired
    private IMerchantsUserService userService;
    @Autowired
    private IMerchantsMenuService menuService;
    @Autowired
    private IMerchantsRoleService roleService;
    @Autowired
    private IMerchantsUserRoleService userRoleService;

    @Override
    public String getToken(String username, String password, String merchantsNo) {
        AdminMerchantsInfo merchantsInfo = merchantsInfoService.getMerchantsByNo(merchantsNo);
        Assert.notNull(merchantsInfo, "商户号不存在");
        TenantUtils.set(merchantsInfo.getId().toString(), merchantsInfo.getMerchantsNo(), merchantsInfo.getName());

        MerchantsUser merchantsUser = userService.getOne(new LambdaQueryWrapper<MerchantsUser>()
                .eq(MerchantsUser::getUsername, username)
                .eq(MerchantsUser::getIsDeleted, CommonConstant.ZERO)
                .last("limit 0,1"));
        Assert.notNull(merchantsUser, "账号信息不存在");
        Assert.isTrue(merchantsUser.getIsEnabled().equals(CommonConstant.ONE), "账号被禁用");
        Assert.isTrue(XXTeaUtil.encrypt(password).equals(merchantsUser.getPassword()), "密码错误");
        return buildToken(merchantsUser, merchantsInfo);
    }

    @Override
    public UserVo getInfo(Integer id) {
        UserVo userVo = baseMapper.getInfo(id);
        List<MerchantsMenu> menus = new ArrayList<>();
        List<MerchantsRole> roles = new ArrayList<>();
        if(userVo.getUserLevel().equals(CommonConstant.ONE)) {
            menus = menuService.getAllMenus();
            roles = roleService.getAllRoles();
        }else {
            menus = menuService.getByUser(userVo.getId());
            roles = roleService.getByUser(userVo.getId());
        }
        userVo.setMenuVos(menus.stream().filter(item-> item.getMenuType().equals(MenuType.MENU.getCode())).map(item-> { return item.getMenuValue(); }).collect(Collectors.toList()));
        userVo.setButtonVos(menus.stream().filter(item-> item.getMenuType().equals(MenuType.BUTTOM.getCode())).map(item-> { return item.getMenuValue(); }).collect(Collectors.toList()));

        userVo.setRoleVos(roles.stream().map(item-> {
            RoleVo vo = new RoleVo();
            BeanUtils.copyProperties(item, vo);
            return vo;
        }).collect(Collectors.toList()));
        return userVo;
    }

    @Override
    public void initAdminUser(SysUserVo sysUserVo) {
        if(this.count(new LambdaQueryWrapper<MerchantsUser>()
                .eq(MerchantsUser::getUsername, sysUserVo.getUsername())) > 0) {
            return;
        }
        this.createUser(CommonConstant.ONE, sysUserVo.getUsername(), sysUserVo.getPassword(), sysUserVo.getPhone(), sysUserVo.getName(), sysUserVo.getIdCard(), sysUserVo.getHeadImage());
    }

    @Override
    public void createUser(Integer userLevel, String username, String password, String phone, String name, String idCard, String headImage) {
        MerchantsUser merchantsUser = new MerchantsUser();
        merchantsUser.setUserLevel(userLevel);
        merchantsUser.setUsername(username);
        merchantsUser.setPassword(password);
        merchantsUser.setPhone(phone);
        merchantsUser.setName(name);
        merchantsUser.setIdCard(idCard);
        merchantsUser.setHeadImg(headImage);
        this.save(merchantsUser);
    }

    @Override
    public IPage<UserVo> getPage(UserDto dto) {
        Page page = Page.of(dto.getPageNumber(), dto.getPageSize());
        return baseMapper.getPage(page, dto);
    }

    @Override
    public UserVo detail(Integer id) {
        return baseMapper.getInfo(id);
    }

    @Override
    public void add(UserForm form) {
        if(this.count(new LambdaQueryWrapper<MerchantsUser>()
                .eq(MerchantsUser::getUsername, form.getUsername())
                .ne(MerchantsUser::getIsDeleted, CommonConstant.ONE)) > 0) {
            throw new BadResponseException("账号【"+ form.getUsername() +"】已存在");
        }
        if(StrUtil.isNotBlank(form.getPhone())) {
            if(this.count(new LambdaQueryWrapper<MerchantsUser>()
                    .eq(MerchantsUser::getPhone, form.getPhone())
                    .ne(MerchantsUser::getIsDeleted, CommonConstant.ONE)) > 0) {
                throw new BadResponseException("手机号【"+ form.getPhone() +"】已有账号信息");
            }
        }
        MerchantsUser merchantsUser = new MerchantsUser();
        BeanUtils.copyProperties(form, merchantsUser);
        merchantsUser.setPassword(XXTeaUtil.encrypt(form.getPassword()));
        this.save(merchantsUser);

        // 角色
        if(ArrayUtil.isAllNotEmpty(form.getRoleIds())) {
            List<MerchantsUserRole> userRoles = form.getRoleIds().stream().map(item-> {
                MerchantsUserRole userRole = new MerchantsUserRole();
                userRole.setUserId(merchantsUser.getId());
                userRole.setRoleId(item);
                return userRole;
            }).collect(Collectors.toList());
            userRoleService.saveBatch(userRoles);
        }
    }

    @Override
    public void edit(UserEditForm form) {
        if(this.count(new LambdaQueryWrapper<MerchantsUser>()
                .eq(MerchantsUser::getUsername, form.getUsername())
                .ne(MerchantsUser::getId, form.getId())
                .ne(MerchantsUser::getIsDeleted, CommonConstant.ONE)) > 0) {
            throw new BadResponseException("账号【"+ form.getUsername() +"】已存在");
        }
        if(StrUtil.isNotBlank(form.getPhone())) {
            if(this.count(new LambdaQueryWrapper<MerchantsUser>()
                    .eq(MerchantsUser::getPhone, form.getPhone())
                    .ne(MerchantsUser::getId, form.getId())
                    .ne(MerchantsUser::getIsDeleted, CommonConstant.ONE)) > 0) {
                throw new BadResponseException("手机号【"+ form.getPhone() +"】已有账号信息");
            }
        }
        MerchantsUser merchantsUser = new MerchantsUser();
        BeanUtils.copyProperties(form, merchantsUser);
        if(StrUtil.isNotBlank(form.getPassword())) {
            merchantsUser.setPassword(XXTeaUtil.encrypt(form.getPassword()));
        }else {
            merchantsUser.setPassword(null);
        }
        this.updateById(merchantsUser);

        // 角色
        userRoleService.remove(new LambdaQueryWrapper<MerchantsUserRole>().eq(MerchantsUserRole::getUserId, merchantsUser.getId()));
        if(ArrayUtil.isAllNotEmpty(form.getRoleIds())) {
            List<MerchantsUserRole> userRoles = form.getRoleIds().stream().map(item-> {
                MerchantsUserRole userRole = new MerchantsUserRole();
                userRole.setRoleId(item);
                userRole.setUserId(merchantsUser.getId());
                return userRole;
            }).collect(Collectors.toList());
            userRoleService.saveBatch(userRoles);
        }
    }

    @Override
    public void delete(Integer id) {
        this.update(new LambdaUpdateWrapper<MerchantsUser>()
                .set(MerchantsUser::getIsDeleted, YesNo.YES.getCode())
                .eq(MerchantsUser::getId, id));
    }

    private String buildToken(MerchantsUser merchantsUser, AdminMerchantsInfo merchantsInfo){
        TenantUser tenantUser = new TenantUser();
        tenantUser.setId(merchantsUser.getId());
        tenantUser.setTenantId(merchantsInfo.getId());
        tenantUser.setUsername(merchantsUser.getUsername());
        tenantUser.setMobile(merchantsUser.getPhone());

        TenantInfo tenantInfo = new TenantInfo();
        tenantInfo.setKey(merchantsInfo.getId().toString());
        tenantInfo.setTenantName(merchantsInfo.getName());
        tenantInfo.setTenantNo(merchantsInfo.getMerchantsNo());
        return TenantTokenUtil.create(tenantUser,tenantInfo).build(30);
    }
}
